<template>
	<view class="base-style"
		:style="'position: relative;width: ' + diameter + 'px;height: ' + diameter + 'px;display: flex;flex-direction: row;background-color: ' + bgColor + ';'">
		<!-- 左半圆和右半圆都要经历下面的5步:
    [第1步]第1层限定区域; 
    [第2步]第2层决定显示一个整圆的左半边还是右半边; 
    [第3步]第3层先使用激活颜色绘制一个圆环, 再添加一个同级且宽度为区域一半的盒子A;
    [第4步]在盒子A中再使用圆环底色绘制一个圆环, 此时整个圆环是 '左一半是激活颜色、右一半是圆环底色', 但这个圆环同时只能被看到一半;
    [第5步]旋转第2层。 -->

		<!-- 左半圆 -->
		<view class="base-style" :style="firstLayerViewStyle">
			<view :style="secondLayerViewStyle + secondLayerForLeft">
				<!-- 使用激活颜色绘制一个圆环。 -->
				<view :style="thirdLayerStyle">
				</view>
				<!-- 再使用背景色遮盖同级圆环的一半。 -->
				<view class="base-style" :style="thirdLayerStyleForBg">
					<view :style="fourthLayerStyleForBg" />
				</view>
				<view v-if="0 < ePercent && ePercent < 0.5" :style="endPointStyle + endPointStyleForLeft" />
			</view>
		</view>

		<!-- 右半圆 -->
		<view class="base-style" :style="firstLayerViewStyle">
			<!-- 适配：为了避免右侧遮盖显示不全 此处向左多移动了1px -->
			<view :style="secondLayerViewStyle + 'left: ' + (- diameter / 2 - 1) + 'px;' + secondLayerForRight">
				<!-- 使用激活颜色绘制一个圆环。 -->
				<view :style="thirdLayerStyle">
				</view>
				<!-- 再使用背景色遮盖同级圆环的一半。 -->
				<view class="base-style" :style="thirdLayerStyleForBg">
					<view :style="fourthLayerStyleForBg" />
				</view>
				<view v-if="ePercent > 0.5" :style="endPointStyle + endPointStyleForRight" />
			</view>
		</view>

		<view v-if="0.5 == ePercent" :style="endPointStyle + 'background-color: ' + this.hoopBgColor + ';'" />
		<!-- #ifdef APP-PLUS -->
		<!-- 处理现象: 安卓App的顶部和底部会有一个小白点。 -->
		<!-- <view v-if="ePercent > 0.5" :style="'position: absolute;top: 0;' + repairPointStyle" /> -->
		<!-- <view v-if="1.0 == ePercent" :style="'position: absolute;bottom: 0;' + repairPointStyle" /> -->
		<!-- #endif -->

		<view class="text" :style="{color: fontColor}">{{percent * 100}}%</view>
	</view>
</template>

<!-- 组件名称： 圆环进度条。
     启发地址： https://www.cnblogs.com/jr1993/p/4677921.html 。
     编者信息： 867003077@qq.com 。 -->
<script>
	export default {
		name: 'progressCircle',
		props: {
			// 百分比字体颜色
			fontColor: {
				type: String,
				default: '#000'
			},
			// 百分比
			percent: {
				type: String,
				default: '0'
			},
			// 背景色（不宜设置为透明 否则 需要 在 左thirdLayer 的外面 再嵌套一个盒子）。
			bgColor: {
				type: String,
				default: '#FFFFFF'
			},
			// 圆环的外直径（单位px）。
			diameter: {
				type: Number,
				default: 250
			},
			// 圆环线条的厚度（单位px）。
			hoopThickness: {
				type: Number,
				default: 8
			},
			// 圆环底色（灰色的圆环）。
			hoopBgColor: {
				type: String,
				// default: 'transparent'
				default: '#F3F3F3'
			},
			// 圆环激活部分的颜色。
			hoopColor: {
				type: String,
				default: '#FF4C20'
			},
			// 圆环进度百分比值（其值范围在0到1之间）。
			percent: {
				type: [Number, String],
				default: 0,
				validator: val => {
					return val >= 0 && val <= 1;
				},
			},
			animate: {
				type: Boolean,
				default: false,
			},
		},
		data() {
			return {
				targetPercent: 0,
				ePercent: 0,
				showTimer: undefined,
			};
		},
		watch: {
			percent: {
				handler: function() {
					console.log('progressCircle_watch_percent', this.percent);
					this.loadData();
				},
			},
		},
		computed: {
			firstLayerViewStyle() {
				return 'position: relative;width: ' + (this.diameter / 2) +
					'px;height: ' + this.diameter + 'px;';
			},
			secondLayerViewStyle() {
				return 'box-sizing: border-box;position: absolute;top: 0;width: ' + this.diameter +
					'px;height: ' + this.diameter + 'px;';
			},
			thirdLayerStyle() {
				return 'box-sizing: border-box;width: ' + this.diameter + 'px;height: ' + this.diameter +
					'px;border-radius: ' + (this.diameter / 2) +
					'px;border-width: ' + this.hoopThickness +
					'px;border-style: solid;border-color: ' + this.hoopColor + ';';
			},
			thirdLayerStyleForBg() {
				return 'box-sizing: border-box;position: absolute;top: 0;left: ' + (this.diameter / 2) + 'px;width: ' +
					this.diameter + 'px;height: ' + this.diameter + 'px;background-color: ' + this.bgColor + ';';
			},
			fourthLayerStyleForBg() {
				return 'box-sizing: border-box;margin-left: ' + (-this.diameter / 2) + 'px;width: ' + this.diameter +
					'px;height: ' +
					this.diameter + 'px;border-radius: ' + (this.diameter / 2) + 'px;border-width: ' +
					this.hoopThickness + 'px;border-style: solid;border-color: ' + this.hoopBgColor + ';';
			},
			secondLayerForLeft() {
				let angle = 0;
				if (this.ePercent < 0.5) {
					angle += (180 * (this.ePercent - 0.5) / 0.5);
				}
				// #ifdef APP-PLUS
				return 'left: 0;transform: rotate(' + angle + 'deg);';
				// #endif
				// #ifndef APP-PLUS
				return 'left: 0;transform: rotate(' + angle + 'deg);-webkit-transform: rotate(' + angle + 'deg);';
				// #endif
			},
			secondLayerForRight() {
				let angle = 0;
				if (this.ePercent > 0.5) {
					angle += (180 * (this.ePercent - 0.5) / 0.5);
				}
				// #ifdef APP-PLUS
				return 'right: 0;transform: rotate(' + angle + 'deg);';
				// #endif
				// #ifndef APP-PLUS
				return 'right: 0;transform: rotate(' + angle + 'deg);-webkit-transform: rotate(' + angle + 'deg);';
				// #endif
			},
			endPointStyle() {
				// 结束点圆心圈直径。
				const _circleCenterRadius = 2;
				return 'box-sizing: border-box;position: absolute;top: 0;left: ' + (this.diameter - this.hoopThickness) /
					2 +
					'px;width: ' +
					this.hoopThickness + 'px;height: ' + this.hoopThickness + 'px;border-radius: ' + (this.hoopThickness /
						2) +
					'px;border-width: ' + (this.hoopThickness / 2 - _circleCenterRadius) +
					'px;border-style: solid;border-color: ' +
					this.hoopColor + ';';
			},
			endPointStyleForLeft() {
				return 'background-color: ' + ((this.ePercent > 0.5) ? this.hoopColor : this.hoopBgColor) + ';';
			},
			endPointStyleForRight() {
				return 'background-color: ' + ((1 == this.ePercent) ? this.hoopColor : this.hoopBgColor) + ';';
			},
		},
		mounted() {
			console.log('progressCircle_mounted');
			this.loadData();
		},
		methods: {
			loadData() {
				this.targetPercent = parseFloat(this.percent);
				console.log('progressCircle_loadData');
				if (!this.animate) {
					this.ePercent = this.targetPercent;
				} else {
					let _this = this;
					this.ePercent = 0;
					this.showTimer && clearInterval(this.showTimer);
					this.showTimer = setInterval(() => {
						let tempPercent = _this.ePercent + 0.1;
						if (tempPercent < _this.targetPercent) {
							_this.ePercent = tempPercent;
							return;
						};
						_this.ePercent = _this.targetPercent;
						clearInterval(_this.showTimer);
					}, 200);
				}
			}
		}
	}
</script>

<style scoped lang="scss">
	.base-style {
		box-sizing: border-box;
		/* 溢出隐藏 */
		overflow: hidden;

		.text {
			position: absolute;
			top: 50%;
			left: 50%;
			transform: translate(-50%, -50%);
		}
	}
</style>